﻿using DotNetty.Codecs.Http;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System.Net;

namespace WebSocketChatServer
{
    /// <summary>
    /// WebSocket是建立在HTTP协议之上,是对Http协议的一种扩展
    /// 除了安装DotNetty.Handlers外,还需要安装DotNetty.Codecs.Http(对http协议支持的包)
    /// </summary>
    internal class Program
    {
        static async Task RunServerAsync()
        {
            MultithreadEventLoopGroup bossGroup = new MultithreadEventLoopGroup();
            MultithreadEventLoopGroup workGroup = new MultithreadEventLoopGroup();

            try
            {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.Group(bossGroup, workGroup)
                    .Channel<TcpServerSocketChannel>()
                    .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
                    {
                        IChannelPipeline pipeline = channel.Pipeline;
                        // HttpServerCodec:包含HttpRequestDecoder解码,HttpResponseEncoder编码
                        // HttpRequestDecoder解码,将HTTP请求的数据解码成请求方法,请求地址,http版本,请求体等
                        // HttpResponseEncoder编码,将响应的数据编码成字节数组
                        pipeline.AddLast(new HttpServerCodec());
                        // 在请求响应过程中,每包http报文并不一定是完整的.HttpObjectAggregator的作用就是将多个不完整的http的片段组成一条完成的http报文(类似前面socket黏包、半包的处理)
                        pipeline.AddLast(new HttpObjectAggregator(8192));
                        pipeline.AddLast(new WebSocketServerHandler());
                    }));

                // IPAddress.Loopback:本地回环地址,127.0.0.1
                IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, 8888);

                Console.ReadKey();
                await bootstrapChannel.CloseAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Task.WaitAll(bossGroup.ShutdownGracefullyAsync(), workGroup.ShutdownGracefullyAsync());
            }
        }

        static async Task Main(string[] args) => await RunServerAsync();
    }
}